home *** CD-ROM | disk | FTP | other *** search
- /*
- * TEXTURE.C Version 1.0a by Lee Lorenz llorenz@delphi.com
- * *WATCOM VERSION*
- * First, Please excuse this mess.
- *
- * Next, Welcome to high-speed image processing... My desire was to
- * rotate/scale a bitmap in real-time, and this was the result.
- * There were plenty of "examples" of texture mapping, in obfuscated
- * highly optimized assembly, but even the "C" and Pascal examples left
- * alot to be desired; after all, I wanted to have more freedom to display
- * images, and didn't want to bother with the trigonometry. With the simple
- * idea of "shooting" a line (Bresenham-style) through a source bitmap, I
- * developed this technique contained in DrawTexture. It may not be original,
- * but I haven't seen it used anywhere else. It can even be augmented with
- * anti-aliasing for image processing. I release this program and technique
- * into the public domain, and I hope to create a highly optimized 386
- * assembler version for my personal library. Please try to credit me when
- * possible, if this shows you anything new or interesting, and you use it
- * in any distributed program (Freeware/shareware/commercial).
- *
- * What this program does:
- * Draws a bitmap into any 4-sided polygon. First vector is upper-left
- * second is upper-right, third is lower-right, and last is lower-left.
- *
- * Limitations:
- * Don't try to use a "Horizontally convex" polygon.
- * Undefined results with intersected polygons
- *
- * What remains to be done:
- * 1. A good intersection-detection routine.
- * 2. A quick 2-D rotation/scaling transform for the corners. I want to
- * be able to "spin" the bitmap/sprite about a point.
- * 3. Possible, slower alternative to scan "horizontal convex" polygons
- * and intersected polygons
- *
- */
-
- #include <stdio.h>
- #include <malloc.h>
- #include <string.h>
- #include <stdlib.h>
- #include <bios.h>
- #include <dos.h>
- #include "gl.h"
- #include <time.h>
-
- int YZSize;
-
- unsigned char ibuff[65000],ipal[768];
-
- struct
- {
- char filename[80];
- int sizex;
- int sizey;
- unsigned char *buff;
- unsigned char *pal;
- } slots[64];
-
-
- struct text_s
- {
- unsigned char *Buffer;
- int XSize,YSize;
- } MyMap;
-
-
- struct quad_s
- {
- int x[4],y[4];
- } MyPoly;
-
- void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug);
-
- void OrderPoly(struct quad_s *poly,unsigned char *order);
-
- /* This routine eliminates intersections by swapping corners
- * if an intersection exists...
- * "adjacent" segments, by nature, cannot intersect, therefore we only
- * need to check opposite segments (AB,CD & DA,BC)
- * Actually, in retrospect, the poly cannot have "horizontal convexity"
- * That is, the scan algorithm cannot handle more than one chunk, Our
- * test, there for is for opposite corners _NOT_ to be next to one another
- * when ordered...
- */
- void UnIntersectQuad(struct quad_s *poly)
- {
- unsigned char work_order[4];
- int i;
-
- OrderPoly(poly,work_order);
- /* Top Convexity/intersection */
- switch(work_order[0])
- {
- case 0: /* Test to insure 2 is not adjacent */
- if(work_order[1]==2)
- {
- /* Swap 1 and 2 */
- i=poly->x[1];
- poly->x[1]=poly->x[2];
- poly->x[2]=i;
- i=poly->y[1];
- poly->y[1]=poly->y[2];
- poly->y[2]=i;
- }
- break;
- case 1: /* Test to insure 3 is not adjacent */
- if(work_order[1]==3)
- {
- /* Swap 0 and 3 */
- i=poly->x[0];
- poly->x[0]=poly->x[3];
- poly->x[3]=i;
- i=poly->y[0];
- poly->y[0]=poly->y[3];
- poly->y[3]=i;
- }
- break;
- case 2: /* Test to insure 0 is not adjacent */
- if(work_order[1]==0)
- {
- /* Swap 1 and 2 */
- i=poly->x[1];
- poly->x[1]=poly->x[2];
- poly->x[2]=i;
- i=poly->y[1];
- poly->y[1]=poly->y[2];
- poly->y[2]=i;
- }
- break;
- case 3: /* Test to insure 1 is not adjacent */
- if(work_order[1]==1)
- {
- /* Swap 0 and 3 */
- i=poly->x[0];
- poly->x[0]=poly->x[3];
- poly->x[3]=i;
- i=poly->y[0];
- poly->y[0]=poly->y[3];
- poly->y[3]=i;
- }
- break;
- }
- OrderPoly(poly,work_order);
- /* BOTTOM Convexity/intersection */
- switch(work_order[3])
- {
- case 0: /* Test to insure 2 is not adjacent */
- if(work_order[2]==2)
- {
- /* Swap 1 and 2 */
- i=poly->x[1];
- poly->x[1]=poly->x[2];
- poly->x[2]=i;
- i=poly->y[1];
- poly->y[1]=poly->y[2];
- poly->y[2]=i;
- }
- break;
- case 1: /* Test to insure 3 is not adjacent */
- if(work_order[2]==3)
- {
- /* Swap 0 and 3 */
- i=poly->x[0];
- poly->x[0]=poly->x[3];
- poly->x[3]=i;
- i=poly->y[0];
- poly->y[0]=poly->y[3];
- poly->y[3]=i;
- }
- break;
- case 2: /* Test to insure 0 is not adjacent */
- if(work_order[2]==0)
- {
- /* Swap 1 and 2 */
- i=poly->x[1];
- poly->x[1]=poly->x[2];
- poly->x[2]=i;
- i=poly->y[1];
- poly->y[1]=poly->y[2];
- poly->y[2]=i;
- }
- break;
- case 3: /* Test to insure 1 is not adjacent */
- if(work_order[2]==1)
- {
- /* Swap 0 and 3 */
- i=poly->x[0];
- poly->x[0]=poly->x[3];
- poly->x[3]=i;
- i=poly->y[0];
- poly->y[0]=poly->y[3];
- poly->y[3]=i;
- }
- break;
- }
- /* Now for intersection test... */
-
- }
-
-
- int LoadSlot(int sl,char *fname);
- void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b);
-
- int lastlength,lastdelta;
-
- unsigned char *ScreenPtr;
-
- struct Pal_s
- {
- unsigned char Red;
- unsigned char Blue;
- unsigned char Green;
- };
-
-
- /*
-
- This algorithm is based on the calculation of the third side of a triangle
- given the known two sides are connected by a right angle.
- This formula is: a^2+b^2=c^2. a and b are the absolute X-Y deltas.
- The first calcluation of c then becomes a, and Z delta becomes b,
- and we do it again. While we _HAVE_ to calculate the squares, it is not needed
- to calc the roots.
-
- i.e. Deltas of 1+1+5=7, 1+2+4=7, but distance is less on second...
- 27 21
-
- Thus, we simply add the squares of all of the absolute deltas.
-
- */
- int FindBestMatch(struct Pal_s *Pal,int r,int g,int b)
- {
- int Distance,i,j,k,R,G,B;
-
- k=12288; j=0;
- for(i=0;i<256;i++)
- {
- R=abs(Pal[i].Red-r);
- R*=R;
- G=abs(Pal[i].Green-g);
- G*=G;
- B=abs(Pal[i].Blue-b);
- B*=B;
- Distance=R+G+B;
- if(Distance<k)
- {
- j=i; k=Distance;
- }
- }
- return(j);
- }
-
- /*
-
- A simple routine to draw a four-sided polygon in a given color.
-
- */
- void DrawPoly(struct quad_s *Poly,int c)
- {
- GL_Line(Poly->x[0],Poly->y[0],Poly->x[1],Poly->y[1],c);
- GL_Line(Poly->x[1],Poly->y[1],Poly->x[2],Poly->y[2],c);
- GL_Line(Poly->x[2],Poly->y[2],Poly->x[3],Poly->y[3],c);
- GL_Line(Poly->x[3],Poly->y[3],Poly->x[0],Poly->y[0],c);
- GL_SetPixel(Poly->x[0],Poly->y[0],c);
- }
-
- unsigned char Order[4];
- int WhiteColor,RedColor,BlackColor,GrayColor;
- int rcount,lcount,rva[8],rvb[8],lva[8],lvb[8],rcnt[8],lcnt[8];
-
- #define ROTATIONS 30
-
- /* I wish DJGPP had a decent random macro!!!!
- * I'll get a 32-bit version done soon
- */
- #define RAND(x) (rand()%x)
-
- int NewDir(int x,int y,int olddir);
- int UpdateX(int x,int direction);
- int UpdateY(int y,int direction);
-
- void main(void)
- {
- long DeltaX,DeltaY,XSize,YSize;
- int i,j,k,NewY;
- /* GrContext ScrCtx; */
- unsigned char *RPtr;
- unsigned char *BuffPtr;
-
- for(i=0;i<64;i++)
- {
- slots[i].filename[0]=0;
- slots[i].pal=NULL;
- slots[i].buff=NULL;
- slots[i].sizex=0;
- slots[i].sizey=0;
- }
- GL_InitMode13();
- slots[0].buff=ibuff;
- slots[0].pal=ipal;
- GL_Gif("bnbtitle.gif",slots[0].buff,slots[0].pal,&slots[0].sizex,&slots[0].sizey);
- /* LoadSlot(0,"bnbtitle.gif"); */
- MyMap.Buffer=slots[0].buff;
- MyMap.XSize=slots[0].sizex;
- MyMap.YSize=slots[0].sizey;
- for(i=0;i<256;i++)
- {
- /* slots[0].pal[i*3]/=4;
- slots[0].pal[(i*3)+1]/=4;
- slots[0].pal[(i*3)+2]/=4; */
- setcolor(i,
- slots[0].pal[i*3],
- slots[0].pal[(i*3)+1],
- slots[0].pal[(i*3)+2]);
- }
- WhiteColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,63,63);
- RedColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,13,13);
- BlackColor=FindBestMatch((struct Pal_s *)slots[0].pal,0,0,0);
- GrayColor=FindBestMatch((struct Pal_s *)slots[0].pal,30,30,30);
- /* GrSaveContext(&ScrCtx); */
- ScreenPtr=(unsigned char *)0x0a0000; /* ScrCtx.gc_baseaddr; */
- RPtr=ScreenPtr;
- XSize=slots[0].sizex*65536;
- YSize=slots[0].sizey*65536;
- DeltaX=XSize/320;
- DeltaY=YSize/200;
- j=0;
- DeltaX=XSize/(320);
- RPtr=ScreenPtr;
- j=0;
- memset(RPtr,0,320*200);
- DeltaX=XSize/320;
- RPtr=ScreenPtr;
- memset(ScreenPtr,BlackColor,320*200);
- MyPoly.x[0]=320/10;
- MyPoly.x[1]=320-(320/15);
- MyPoly.x[2]=320-(320/5);
- MyPoly.x[3]=320/12;
- MyPoly.y[0]=200/20;
- MyPoly.y[1]=200/10;
- MyPoly.y[2]=200-(200/15);
- MyPoly.y[3]=200-(200/25);
- DrawPoly(&MyPoly,WhiteColor);
- DrawTexture(&MyPoly,&MyMap,0);
- while(!kbhit())
- {
- rand();
- for(i=0;i<ROTATIONS;i++)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[0]=(319*(i+1))/ROTATIONS;
- MyPoly.x[1]=319;
- MyPoly.x[2]=319-(319*(i+1))/ROTATIONS;
- MyPoly.x[3]=0;
- MyPoly.y[0]=0;
- MyPoly.y[1]=(199*(i+1))/ROTATIONS;
- MyPoly.y[2]=199;
- MyPoly.y[3]=199-(199*(i+1))/ROTATIONS;
- DrawPoly(&MyPoly,RedColor);
- DrawTexture(&MyPoly,&MyMap,0);
- }
- for(i=0;i<ROTATIONS;i++)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[3]=(319*(i+1))/ROTATIONS;
- MyPoly.x[0]=319;
- MyPoly.x[1]=319-(319*(i+1))/ROTATIONS;
- MyPoly.x[2]=0;
- MyPoly.y[3]=0;
- MyPoly.y[0]=(199*(i+1))/ROTATIONS;
- MyPoly.y[1]=199;
- MyPoly.y[2]=199-(199*(i+1))/ROTATIONS;
- DrawPoly(&MyPoly,WhiteColor);
- DrawTexture(&MyPoly,&MyMap,0);
- }
- for(i=0;i<ROTATIONS;i++)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[2]=(319*(i+1))/ROTATIONS;
- MyPoly.x[3]=319;
- MyPoly.x[0]=319-(319*(i+1))/ROTATIONS;
- MyPoly.x[1]=0;
- MyPoly.y[2]=0;
- MyPoly.y[3]=(199*(i+1))/ROTATIONS;
- MyPoly.y[0]=199;
- MyPoly.y[1]=199-(199*(i+1))/ROTATIONS;
- DrawPoly(&MyPoly,RedColor);
- DrawTexture(&MyPoly,&MyMap,0);
- }
- for(i=0;i<ROTATIONS;i++)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[1]=(319*(i+1))/ROTATIONS;
- MyPoly.x[2]=319;
- MyPoly.x[3]=319-(319*(i+1))/ROTATIONS;
- MyPoly.x[0]=0;
- MyPoly.y[1]=0;
- MyPoly.y[2]=(199*(i+1))/ROTATIONS;
- MyPoly.y[3]=199;
- MyPoly.y[0]=199-(199*(i+1))/ROTATIONS;
- DrawPoly(&MyPoly,WhiteColor);
- DrawTexture(&MyPoly,&MyMap,0);
- }
- }
- while(kbhit())
- getch();
- while(!kbhit())
- {
- rand();
- for(i=0;i<20;i++)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[0]=0-(i*8);
- MyPoly.x[1]=319+(i*8);
- MyPoly.x[2]=319+(i*8);
- MyPoly.x[3]=0-(i*8);
- MyPoly.y[0]=0-(i*8);
- MyPoly.y[1]=0-(i*8);
- MyPoly.y[2]=199+(i*8);
- MyPoly.y[3]=199+(i*8);
- /* DrawPoly(&MyPoly,RedColor); */
- DrawTexture(&MyPoly,&MyMap,0);
- }
- for(i=20;i;i--)
- {
- rand();
- if(kbhit())
- break;
- MyPoly.x[0]=0-(i*8);
- MyPoly.x[1]=319+(i*8);
- MyPoly.x[2]=319+(i*8);
- MyPoly.x[3]=0-(i*8);
- MyPoly.y[0]=0-(i*8);
- MyPoly.y[1]=0-(i*8);
- MyPoly.y[2]=199+(i*8);
- MyPoly.y[3]=199+(i*8);
- /* DrawPoly(&MyPoly,RedColor); */
- DrawTexture(&MyPoly,&MyMap,0);
- }
- }
- while(kbhit())
- getch();
- i=1;
- j=2;
- k=3;
- NewY=0; /* Directions of points */
- while(!kbhit())
- {
- MyPoly.x[0]=UpdateX(MyPoly.x[0],i);
- MyPoly.y[0]=UpdateY(MyPoly.y[0],i);
- i=NewDir(MyPoly.x[0],MyPoly.y[0],i);
-
- MyPoly.x[1]=UpdateX(MyPoly.x[1],j);
- MyPoly.y[1]=UpdateY(MyPoly.y[1],j);
- j=NewDir(MyPoly.x[1],MyPoly.y[1],j);
-
- MyPoly.x[2]=UpdateX(MyPoly.x[2],k);
- MyPoly.y[2]=UpdateY(MyPoly.y[2],k);
- k=NewDir(MyPoly.x[2],MyPoly.y[2],k);
-
- MyPoly.x[3]=UpdateX(MyPoly.x[3],NewY);
- MyPoly.y[3]=UpdateY(MyPoly.y[3],NewY);
- NewY=NewDir(MyPoly.x[3],MyPoly.y[3],NewY);
-
- /* memset(RPtr,0,320*200); */
- UnIntersectQuad(&MyPoly);
- DrawTexture(&MyPoly,&MyMap,0);
- }
- while(kbhit())
- getch();
- getch();
- GL_TextMode();
- /* GrSetMode(GR_default_text); */
- }
-
- /*
- * Convenience function... update the direction, if needed
- */
- int NewDir(int x,int y,int olddir)
- {
- if(x<=0)
- {
- if(y<=0)
- {
- return(3);
- }
- else
- {
- if(y>=199)
- {
- return(1);
- }
- return(RAND(3)+1);
- }
- }
- else
- {
- if(x>=319)
- {
- if(y<=0)
- {
- return(5);
- }
- else
- {
- if(y>=199)
- {
- return(7);
- }
- return(RAND(3)+5);
- }
- }
- else
- {
- if(y<=0)
- {
- return(RAND(3)+3);
- }
- else
- {
- if(y>=199)
- {
- olddir=RAND(3); if(olddir==2) olddir=7;
- return(olddir);
- }
- return(olddir);
- }
- }
- }
- }
-
- /*
- * Convenience function... update the X-Co-ord given a direction
- */
- int UpdateX(int x,int direction)
- {
- switch(direction)
- {
- case 0: /* UP */
- case 4:
- return(x);
- break;
- case 1: /* UP-RIGHT */
- case 2:
- case 3:
- return(x+1);
- break;
- case 5:
- case 6:
- case 7:
- return(x-1);
- break;
- }
- return(x);
- }
-
- /*
- * Convenience function... update the Y-Co-ord given a direction
- */
- int UpdateY(int y,int direction)
- {
- switch(direction)
- {
- case 2:
- case 6:
- return(y);
- break;
- case 0: /* UP */
- case 1: /* UP-RIGHT */
- case 7:
- return(y-1);
- break;
- case 3:
- case 4:
- case 5:
- return(y+1);
- break;
- }
- return(y);
- }
-
- void disable(void);
- void enable(void);
-
-
- #pragma aux disable = "cli"
- #pragma aux enable = "sti"
-
-
-
- /*
- * Program the RAMDAC 256-color palette. Seems like I'm _ALWAYS_ re-inventing
- * this one!
- */
- void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b)
- {
- disable();
- outp(0x3c8,c);
- inp(0x80);
- outp(0x3c9,r);
- inp(0x80);
- outp(0x3c9,g);
- inp(0x80);
- outp(0x3c9,b);
- enable();
- }
-
- /*
- * Return an array of vector IDs sorted by Y value
- */
- void OrderPoly(struct quad_s *poly,unsigned char *order)
- {
- int i,j,x,y;
-
- for(i=0;i<4;i++)
- {
- order[i]=(unsigned char)i;
- }
- for(i=0;i<3;i++)
- {
- for(j=(i+1);j<4;j++)
- {
- if(poly->y[order[j]]<poly->y[order[i]])
- {
- x=order[i]; order[i]=order[j]; order[j]=x;
- }
- }
- }
- }
-
-
- /*
- * General purpose linear conversion routine
- * I use a more complex version at work that reduces precision to prevent
- * overflows.
- */
- long lconvert(long a,long b,long c)
- {
- if(b)
- {
- return((a*c)/b);
- }
- return(0);
- }
-
- /*
- * Return an arbitrary X point on a given line
- */
- int XPoint(int x1,int y1,int x2,int y2,int ny)
- {
- int z;
-
- x2-=x1;
- y2-=y1;
- ny-=y1;
- z=lconvert(x2,y2,ny);
- return(z+x1);
- }
-
- /*
- * Return an arbitrary Y point on a given line
- */
- int YPoint(int x1,int y1,int x2,int y2,int nx)
- {
- int z;
-
- x2-=x1;
- y2-=y1;
- nx-=x1;
- z=lconvert(y2,x2,nx);
- return(z+y1);
- }
-
- /*
- * Returns a floating point version of a 16.16 signed fixed point number
- */
- float fixed2float(long z)
- {
- int sign;
- unsigned long whole,fraction;
- float result;
-
- sign=0;
- if(z<0)
- {
- sign=1;
- z=0-z;
- }
- whole=z>>16;
- fraction=z&0x0ffff;
- result=(float)(fraction); result/=65536.0;
- result+=(float)(whole);
- if(sign) result=0.0-result;
- return(result);
- }
-
- /*
- * What we do, is for each Screen Y, we draw a line of texture
- *
- *
- * This routine cannot handle "horizontal convexity", that is, when we
- * get two chunks to draw on the same scan line. The program will freak out,
- * so "UnIntersectQuad" is used to "remove" the convexity... normally, you
- * would just avoid this situation. Likewise, the routine doesn't like
- * intersections too much, but surprisingly, the program won't blow any
- * serious chunks, as long as the convexity is taken care of. Images can
- * be flipped, by re-ordering the corners of your polygon.
- * Polygon Co-ordinates can range from -32768 to 32767, as I use SIGNED
- * 16.16bit fixed point numbers.
- *
- *
- */
- void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug)
- {
- long i,j,k,ysize;
- long LeftVectorA,LeftVectorB,RightVectorA,RightVectorB;
- long YCheck,LeftSegment,RightSegment,m,n,o,p,q,OSize;
- long LeftDelta,LeftStartX,RightDelta;
- long L_Size,R_Size,LeftBDeltaX,LeftBDeltaY;
- long RightBDeltaX,RightBDeltaY,RightXPos,RightYPos;
- long LeftXPos,LeftYPos,LeftCount,RightCount,LeftX,RightX;
- unsigned char *screenptr;
-
- lcount=rcount=1;
- OrderPoly(poly,Order); /* Order now holds points from top to bottom */
- ysize=poly->y[Order[3]]-poly->y[Order[0]]; /* Total screen Y Size */
- YZSize=ysize;
- if(ysize<3) /* Don't even try if too small */
- return;
- YCheck=poly->y[Order[3]]; /* 'Lowest' Y+some amount */
- /* Now, load data for first two segments... */
- screenptr=ScreenPtr;
- i=320*poly->y[Order[0]];
- screenptr+=i;
- i=0; j=0; k=0;
- m=(Order[0]+1)%4; n=(Order[0]+3)%4;
- while(i==j && k<3)
- {
- YCheck+=20;
- i=XPoint(poly->x[Order[0]],poly->y[Order[0]],
- poly->x[m],poly->y[m],YCheck);
- j=XPoint(poly->x[Order[0]],poly->y[Order[0]],
- poly->x[n],poly->y[n],YCheck);
- k++;
- }
- if(k==3)
- {
- /* Either, invalid, or flat line! */
- i=poly->x[m]; j=poly->x[n];
- if(i==j)
- return; /* Invalid polygon... */
- }
- LeftVectorA=Order[0];
- RightVectorA=Order[0];
- if(i<j) /* 0,m is LEFT edge */
- {
- LeftVectorB=m; RightVectorB=n;
- LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
- RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
- L_Size=LeftCount;
- R_Size=RightCount;
- i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
- LeftDelta=lconvert(i,LeftCount,65536);
- j=poly->x[RightVectorB]-poly->x[RightVectorA];
- RightDelta=lconvert(j,RightCount,65536);
- LeftX=poly->x[LeftVectorA]*65536;
- RightX=LeftX;
- }
- else
- {
- LeftVectorB=n; RightVectorB=m;
- LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
-
- RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
- L_Size=LeftCount;
- R_Size=RightCount;
- i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
- LeftDelta=lconvert(i,LeftCount,65536);
-
- j=poly->x[RightVectorB]-poly->x[RightVectorA];
- RightDelta=lconvert(j,RightCount,65536);
- LeftX=poly->x[LeftVectorA]*65536;
- RightX=LeftX;
- }
- switch((LeftVectorA<<2)|LeftVectorB)
- {
- case 0: /* A-A Impossible */
- case 2: /* A-C Impossible */
- case 5: /* B-B Impossible */
- case 7: /* B-D Impossible */
- case 8: /* C-A Impossible */
- case 10: /* C-C Impossible */
- case 13: /* D-B impossible */
- case 15: /* D-D Impossible */
- break;
- case 1: /* A-B */
- LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=0; LeftYPos=0;
- break;
- case 3: /* A-D */
- LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=0; LeftYPos=0;
- break;
- case 4: /* B-A */
- LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=Texture->XSize-1; LeftYPos=0;
- break;
- case 6: /* B-C */
- LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=Texture->XSize-1; LeftYPos=0;
- break;
- case 9: /* C-B */
- LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
- break;
- case 11: /* C-D */
- LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
- break;
- case 12: /* D-A */
- LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=0; LeftYPos=Texture->YSize-1;
- break;
- case 14: /* D-C */
- LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=0; LeftYPos=Texture->YSize-1;
- break;
- }
- switch((RightVectorA<<2)|RightVectorB)
- {
- case 0: /* A-A Impossible */
- case 2: /* A-C Impossible */
- case 5: /* B-B Impossible */
- case 7: /* B-D Impossible */
- case 8: /* C-A Impossible */
- case 10: /* C-C Impossible */
- case 13: /* D-B impossible */
- case 15: /* D-D Impossible */
- break;
- case 1: /* A-B */
- RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=0; RightYPos=0;
- break;
- case 3: /* A-D */
- RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=0; RightYPos=0;
- break;
- case 4: /* B-A */
- RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=Texture->XSize-1; RightYPos=0;
- break;
- case 6: /* B-C */
- RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=Texture->XSize-1; RightYPos=0;
- break;
- case 9: /* C-B */
- RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
- break;
- case 11: /* C-D */
- RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
- break;
- case 12: /* D-A */
- RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=0; RightYPos=Texture->YSize-1;
- break;
- case 14: /* D-C */
- RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=0; RightYPos=Texture->YSize-1;
- break;
- }
- LeftXPos*=65536; LeftYPos*=65536;
- RightXPos*=65536; RightYPos*=65536;
- lva[0]=LeftVectorA;
- lvb[0]=LeftVectorB;
- rva[0]=RightVectorA;
- rvb[0]=RightVectorB;
- lcnt[0]=LeftCount;
- rcnt[0]=RightCount;
- for(i=0;i<ysize;i++)
- {
- m=poly->y[Order[0]]+i;
- if(m>199)
- break;
- if(!LeftCount)
- {
- /* Get next Left Vector */
- j=LeftVectorB; k=(LeftVectorB+1)%4;
- if(k==LeftVectorA)
- {
- k=(LeftVectorB+3)%4;
- }
- LeftVectorA=j; LeftVectorB=k;
- LeftX=poly->x[LeftVectorA]*65536;
- LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
- lva[lcount]=LeftVectorA;
- lvb[lcount]=LeftVectorB;
- lcnt[lcount]=LeftCount;
- lcount++;
- j=poly->x[LeftVectorB]-poly->x[LeftVectorA];
- L_Size=LeftCount;
- LeftDelta=lconvert(j,LeftCount,65536);
- switch((LeftVectorA<<2)|LeftVectorB)
- {
- case 0: /* A-A Impossible */
- case 2: /* A-C Impossible */
- case 5: /* B-B Impossible */
- case 7: /* B-D Impossible */
- case 8: /* C-A Impossible */
- case 10: /* C-C Impossible */
- case 13: /* D-B impossible */
- case 15: /* D-D Impossible */
- break;
- case 1: /* A-B */
- LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=0; LeftYPos=0;
- break;
- case 3: /* A-D */
- LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=0; LeftYPos=0;
- break;
- case 4: /* B-A */
- LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=Texture->XSize-1; LeftYPos=0;
- break;
- case 6: /* B-C */
- LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=Texture->XSize-1; LeftYPos=0;
- break;
- case 9: /* C-B */
- LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
- break;
- case 11: /* C-D */
- LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
- break;
- case 12: /* D-A */
- LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
- LeftBDeltaX=0;
- LeftXPos=0; LeftYPos=Texture->YSize-1;
- break;
- case 14: /* D-C */
- LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
- LeftBDeltaY=0;
- LeftXPos=0; LeftYPos=Texture->YSize-1;
- break;
- }
- LeftXPos*=65536; LeftYPos*=65536;
-
- }
- if(!RightCount)
- {
- /* Get next Right Vector */
- j=RightVectorB; k=(RightVectorB+1)%4;
- if(k==RightVectorA)
- {
- k=(RightVectorB+3)%4;
- }
- RightVectorA=j; RightVectorB=k;
- RightX=poly->x[RightVectorA]*65536;
- RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
- R_Size=RightCount;
- rva[rcount]=RightVectorA;
- rvb[rcount]=RightVectorB;
- rcnt[rcount]=RightCount;
- rcount++;
- j=poly->x[RightVectorB]-poly->x[RightVectorA];
- RightDelta=lconvert(j,RightCount,65536);
- switch((RightVectorA<<2)|RightVectorB)
- {
- case 0: /* A-A Impossible */
- case 2: /* A-C Impossible */
- case 5: /* B-B Impossible */
- case 7: /* B-D Impossible */
- case 8: /* C-A Impossible */
- case 10: /* C-C Impossible */
- case 13: /* D-B impossible */
- case 15: /* D-D Impossible */
- break;
- case 1: /* A-B */
- RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=0; RightYPos=0;
- break;
- case 3: /* A-D */
- RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=0; RightYPos=0;
- break;
- case 4: /* B-A */
- RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=Texture->XSize-1; RightYPos=0;
- break;
- case 6: /* B-C */
- RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=Texture->XSize-1; RightYPos=0;
- break;
- case 9: /* C-B */
- RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
- break;
- case 11: /* C-D */
- RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
- break;
- case 12: /* D-A */
- RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
- RightBDeltaX=0;
- RightXPos=0; RightYPos=Texture->YSize-1;
- break;
- case 14: /* D-C */
- RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
- RightBDeltaY=0;
- RightXPos=0; RightYPos=Texture->YSize-1;
- break;
- }
- RightXPos*=65536; RightYPos*=65536;
- }
- /* Now, We can shoot our row... */
- j=(LeftXPos/65536); j+=((LeftYPos/65536)*Texture->XSize);
- /* j=offset into bitmap... */
- k=(RightX-LeftX)/65536; /* Size of line... */
- if(m<0) k=0; /* Skip if above screen */
- m=LeftX/65536; n=RightX/65536;
- if((n<0)||(m>319))
- {
- k=0; /* No line to be draw... */
- }
- if(k)
- {
- OSize=k;
- p=LeftXPos; q=LeftYPos;
- o=LeftX/65536;
- if(m<0)
- {
- if((m+k)>0) /* Clip Left Boundary */
- {
- m=-m;
- p+=(((RightXPos-LeftXPos)/k)*m);
- q+=(((RightYPos-LeftYPos)/k)*m);
- o+=m;
- }
- else
- k=0;
- }
- if(n>319) /* Clip Right boundary */
- {
- n-=319;
- k-=n;
- }
- }
- /*
- This is the "inner" loop. Clipping has already been done.
- "p" is our fixed point bitmap X position
- "q" is our fixed point bitmap Y position
- "m" is our starting screen X position
- */
- if(k>2)
- {
- m=(RightXPos-LeftXPos)/OSize; n=(RightYPos-LeftYPos)/OSize;
- /* m and n equal deltas for bitmap ray */
- if(debug)
- {
- if(getch()==' ')
- {
- GL_TextMode();
- /* GrSetMode(GR_default_text); */
- printf("XInc= %f YInc=%f OSize=%d",fixed2float(m),
- fixed2float(n),OSize);
- printf("ScreenPos=%d P=%f Q=%f\n",o,
- fixed2float(p),fixed2float(q));
-
- printf("LeftX=%f RightX=%f ",fixed2float(LeftXPos),
- fixed2float(RightXPos));
- printf("LeftY=%f RightY=%f ",fixed2float(LeftYPos),
- fixed2float(RightYPos));
- printf("(%c-%c)/(%c-%c)\n",
- LeftVectorA+'A',LeftVectorB+'A',RightVectorA+'A',
- RightVectorB+'A');
- printf(
- "L_Size=%d R_Size=%d LeftCount=%d RightCount=%d\n",
- L_Size,R_Size,LeftCount,RightCount);
- printf("A(%d,%d) B(%d,%d) C(%d,%d) D(%d,%d)\n",
- poly->x[0],poly->y[0],poly->x[1],poly->y[1],
- poly->x[2],poly->y[2],poly->x[3],poly->y[3]);
- exit(0);
- }
- }
- for(;k;k--,o++)
- {
- j=(p/65536); j+=((q/65536)*Texture->XSize);
- screenptr[o]=Texture->Buffer[j];
- p+=m; q+=n;
- }
- }
- /* Ending position in bitmap... */
- LeftCount--; RightCount--;
- RightXPos+=RightBDeltaX;
- RightYPos+=RightBDeltaY;
- LeftXPos+=LeftBDeltaX;
- LeftYPos+=LeftBDeltaY;
- LeftX+=LeftDelta;
- RightX+=RightDelta;
- screenptr+=320;
-
- }
-
- }
-
-
-
-